package com.scaffold.commons.json;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.type.TypeFactory;

import wangjg.commons.bean.BeanUtil;

import com.scaffold.card.entity.Card;

/**
 * 
 * @author wangjg
 *
 */
public class JacksonUtil {
	public static Boolean beautifier = false;
	
	private ApiObjectMapper mapper = new ApiObjectMapper();
	
	public JacksonUtil() {
		this.mapper.init();
	}

	public ObjectMapper getMapper(){
		return mapper;
	}
	
	public String objToJson(Object obj){
		try {
			if(beautifier){
				return this.getMapper().writerWithDefaultPrettyPrinter().writeValueAsString(obj);
			}else{
				return this.getMapper().writeValueAsString(obj);
			}
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
	
	public String objToPrettyJson(Object obj){
		try {
			String json = this.getMapper().writerWithDefaultPrettyPrinter().writeValueAsString(obj);
			return json;
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	public Object jsonToObj(String jsonStr, Class<?> cls) {
		if (jsonStr == null || cls==null){
			return null;
		}
		try{
			return this.getMapper().readValue(jsonStr, cls);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
	
	public <T> List<T> jsonToList(String jsonVal, Class<?> clazz) {
		TypeFactory tf = TypeFactory.defaultInstance();
		try{
			List<T> list = this.getMapper().readValue(jsonVal, tf.constructCollectionType(ArrayList.class, clazz));
			return list;
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
	
	@SuppressWarnings("all")
	public List jsonToList(String jsonVal){
		try{
			List list = this.getMapper().readValue(jsonVal, List.class);
			return list;
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	public Map<?,?> jsonToMap(String jsonVal) {
		try{
			Map<?,?> map = this.getMapper().readValue(jsonVal, Map.class);
			return map;
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 分多个数组
	 * @param list
	 * @return
	 */
	public Map<String,Object> cutJsonList(List<Object> list){
		HashSet<String> ppSet = new HashSet<String>();
		List<Map<String,Object>> maplList = new ArrayList<Map<String,Object>>();
		for(Object bean : list){
			Map<String,Object> objMap = BeanUtil.getObjectMap(bean, true);
			maplList.add(objMap);
			
			ppSet.addAll(objMap.keySet());
		}

		List<Object> valList = new ArrayList<Object>();
		for(Map<String,Object> objMap : maplList){
			List<Object> vList = new ArrayList<Object>();
			for(String pp : ppSet){
				Object val = objMap.get(pp);
				vList.add(val);
			}
			valList.add(vList);
		}
		
		Map<String,Object> map = new LinkedHashMap<String,Object>();
		map.put("p", ppSet);
		map.put("v", valList);
		
		return map;
	}
	
	/**
	 * 一个数组
	 * @param list
	 * @return
	 */
	public Map<String,Object> cutJsonList2(List<?> list){
		HashSet<String> ppSet = new HashSet<String>();
		List<Map<String,Object>> maplList = new ArrayList<Map<String,Object>>();
		for(Object bean : list){
			Map<String,Object> objMap = BeanUtil.getObjectMap(bean, true);
			maplList.add(objMap);
			
			ppSet.addAll(objMap.keySet());
		}

		List<Object> valList = new ArrayList<Object>();
		for(Map<String,Object> objMap : maplList){
			for(String pp : ppSet){
				Object val = objMap.get(pp);
				if(val!=null){
					valList.add(val);	
				}else{
					valList.add(val);
				}
			}
		}
		
		Map<String,Object> map = new LinkedHashMap<String,Object>();
		map.put("p", ppSet);
		map.put("v", valList);
		map.put("#", "L");
		
		return map;
	}
	
	@SuppressWarnings("unchecked")
	public List<?> unCutJsonList2(Map<String,Object> map, Class<?> cls){
		List<String> ppList = (List<String>) map.get("p");
		List<Object> valList = (List<Object>) map.get("v");
		
		List<Object> objList = new ArrayList<Object>();
		Object bean = null;
		for(int i=0;i<valList.size();i++){
			int pIndex = i % ppList.size();
			String pp = ppList.get(pIndex);
			Object pv = valList.get(i);
			if(pIndex==0){
				try {
					bean = cls.newInstance();
				} catch (Exception e) {
					throw new RuntimeException(e);
				}
				objList.add(bean);
			}
			if(pv!=null){
//				BeanUtil.setNestedProperty(bean, pp, pv);
				try {
					BeanUtils.setProperty(bean, pp, pv);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		return objList;
	}
	
	public static void main(String[] args) throws Exception {
		List<Object> list = new ArrayList<Object>();
		Card bean = new Card();
		bean.setId(1L);
		bean.setPicture("xxx");
		bean.setCategoryId(5L);
		list.add(bean);
		list.add(bean);
		
		Card bean3 = new Card();
		bean3.setId(1L);
		bean3.setVideo("d:\\a.mp4");
		list.add(bean3);

		JacksonUtil ju = new JacksonUtil();
		System.out.println(list.size());
		System.out.println(ju.objToJson(list));
		System.out.println(ju.objToJson(ju.cutJsonList(list)));
		System.out.println(ju.objToJson(ju.cutJsonList2(list)));
		System.out.println(ju.objToJson("ab\"c,\t\n"));
		System.out.println(ju.jsonToList("[1,null,3]"));
		
		Map<String, Object> map = (Map<String, Object>) ju.jsonToMap(ju.objToJson(ju.cutJsonList2(list)));
		System.out.println(ju.unCutJsonList2(map, Card.class));

	}
}

